home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ham Radio 2000
/
Ham Radio 2000.iso
/
ham2000
/
tcp_ip
/
gp
/
7plsrc.lzh
/
DECODE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-12-29
|
21KB
|
684 lines
#include "7plus.h"
#include "globals.h"
/*
*** If there's no extension in the filename, try, if a correctionfile
*** already exists. If it does, correct. decode afterwards.
***
*/
int control_decode (char *name)
{
int i;
char newname[MAXPATH];
i = 0;
*_ext = EOS;
fnsplit (name, NULL, NULL, NULL, _ext);
if (!*_ext)
{
sprintf (newname, "%s.cor", name);
if (!test_exist (newname))
i = decode_file (newname);
}
if (!i)
i= decode_file (name);
return (i);
}
/*
*** decode a file. create error report, do correction.
***
***
*/
int decode_file (char *name)
{
FILE *rein, *raus, *report;
int part, teil, parts, teile, parts0;
int czeile, czeile2, fzeilen, zeilen, blockzeilen, blockz0;
int lokaldefekt, defekt, rest, laenge, correct, hcorrupted;
int corrpart, corrzeile, corrected, rebuilt, cor_ok, ignored;
uint csequence, crc, ascbytes, ascb0;
ulong danach[16], *dn;
long binbytes, binb0, binb1;
char zeile[81], *p, buf[81], dummi[20], dummi2[81], dummi3[20];
char inpath[MAXFPATH], filename[13];
char quellname[MAXPATH], rausname[MAXFNAME], orgname[MAXFNAME];
char orgname2[66], zielname[13], ziel0[13], reportname[13];
register i, j, k;
*buf = *orgname = EOS;
raus = NULL;
hcorrupted = 0;
/* Isolate input-path and filename */
fnsplit (name, _drive, _dir, _file, _ext);
sprintf (inpath, "%s%s", _drive, _dir);
build_DOS_name (_file);
build_DOS_name (_ext);
_file[8] = _ext[3] = EOS;
sprintf (filename, "%s%s%s", _file, _ext[0]?".":"", _ext);
correct = ignored = 0;
/* If ext ist COR, then open COR-file and check for validity */
if (!strncmp (_ext, "cor", 4))
{
correct = 1;
cor_ok = 0;
if (crc_file (name, "7PLUS corr", " P00:\n", 1) == 1)
return (7);
report = fopen (name, OPEN_READ_TEXT);
/* Find starting line */
while ((p = my_fgets (zeile, 80, report)) != NULL)
if (!strncmp (zeile, "7PLUS corr", 10))
break;
if (!p)
{
printf ("\007Invalid correction file.\n Break.");
return (7);
}
/* Get filename from starting line */
binb1 = 0L;
sscanf (zeile, "7PLUS correction: %12s %ld", filename, &binb1);
/* Strip ext from filename */
if ((p = strrchr (filename, '.')) != NULL)
*p++ = EOS;
strlwr (filename);
strcpy (zielname, filename);
/* Get first number of part and line to correct */
my_fgets (dummi2, 80, report);
corrpart = get_hex (dummi2+2);
my_fgets (dummi2, 80, report);
corrzeile = get_hex (dummi2+2);
}
/* If no ext or correction needed, generate filename */
if (!*_ext || correct)
{
sprintf (quellname, "%s%s.7pl", inpath, filename);
if ((rein = fopen (quellname, OPEN_READ_TEXT)) != NULL)
{
fclose (rein);
strcat (filename, ".7pl");
}
else
strcat (filename, ".p01");
}
sprintf (quellname, "%s%s", inpath, filename);
/* open input file */
if ((rein = fopen (quellname, OPEN_READ_BINARY)) == NULL)
{
printf (cant, filename);
return (2);
}
/* Set I/O-buffering */
setvbuf (rein, NULL, _IOFBF, buflen);
if (correct)
printf ("\nCorrecting...\n\n");
else
printf ("\nDecoding...\n\n");
defekt = 0;
parts = 1;
/* Loop for number of parts. At beginning of first round, number of parts
unknown, that's why parts is set to 1 */
for (part = 1; part < parts +1; part++)
{
if (part == 256)
{
printf ("\007\nMore than 255 parts not allowed. Break.\n");
kill_dest (rein, raus, orgname);
return (8);
}
/* If we're already at part > 1, generate filename for next part. */
if (part != 1)
{
sprintf (filename, "%s.p%02x", zielname, part);
sprintf (quellname, "%s%s", inpath, filename);
if ((rein = fopen (quellname, OPEN_READ_BINARY)) == NULL)
{
printf ("\007\n'%s': Not found. Break.\n", filename);
kill_dest (rein, raus, orgname);
return (2);
}
setvbuf (rein, NULL, _IOFBF, buflen);
}
/* Read, until starting line is found. */
while ((p = my_fgets (zeile, 80, rein)) != NULL)
if (!strncmp (zeile, " go_7+. ", 7))
break;
/* p == NULL? then no starting line found. File no good. */
if (!p)
{
printf ("\007'%s': 7PLUS-startline ", filename);
printf ("not found. Break.\n");
kill_dest (rein, raus, orgname);
return (3);
}
if (!mcrc (zeile, 0))
rebuild (zeile, 1);
/* Check if file went trough 7bit channel */
if (!strstr (zeile, "\xb0\xb1"))
{
printf ("\007\n'%s':\nBit 8 has been stripped! Can't decode.\n", filename);
printf ("Please check all settings of your terminal and tnc\n");
printf ("regarding 8 bit transfer.\n");
printf ("You will have to re-read '%s' from the mailbox\n");
printf ("after having corrected the settings.\n");
fclose (rein);
return (9);
}
/* Get info from 7PLUS header */
if(sscanf (zeile+8, "%d %s %d %s %ld %s %s %s %s %s",
&teil, dummi, &teile, zielname,
&binbytes, dummi2, dummi3, dummi, dummi, dummi) != 10)
hcorrupted = 1;
ascbytes = get_hex (dummi2);
blockzeilen = get_hex (dummi3);
fzeilen = (int) (ascbytes / 64) -1; /* Number of lines in this file */
strlwr (zielname); /* Convert to lower case */
if (strlen (dummi) == 5)
if (!mcrc(zeile, 0))
hcorrupted = 1;
if (teil == 1 && !hcorrupted)
{
parts0 = teile;
strcpy (ziel0, zielname);
binb0 = binbytes;
ascb0 = ascbytes;
blockz0 = blockzeilen;
}
if ((parts0 != teile || stricmp(ziel0, zielname) || binb0 != binbytes ||
blockz0 != blockzeilen) && !hcorrupted)
hcorrupted = 1;
if (part == parts0 && !hcorrupted)
{
if (binb0 % (blockz0 *62))
ascb0 = (uint) (binb0 % (blockz0 *62));
else
ascb0 = blockz0 *62;
ascb0 = ((ascb0 +61) /62) *64;
}
if (ascb0 != ascbytes && !hcorrupted)
hcorrupted = 1;
if (correct && binb1)
{
if (binb1 != binbytes)
{
printf (notsame, "correction file");
kill_dest (rein, raus, orgname);
return (15);
}
}
if (hcorrupted)
{
printf ("'%s': Header is corrupted. Can't continue", quellname);
kill_dest (rein, raus, orgname);
return(5);
}
/* If first part, process filename, calculate how many valid binary bytes
are contained in last code line of last part. */
if (teil == 1)
{
*orgname2 = *buf = EOS;
if (dummi[3] == '*')
{
if (correct)
strcpy (buf, zeile);
my_fgets (zeile, 80, rein);
if (!mcrc (zeile, 0))
{
printf ("\n\nExtended Filename corrupted. Using filename from header.\n\n");
strcpy (orgname2, zielname);
}
else
sscanf (zeile, "/%60[^/]", orgname2);
}
strcpy (orgname, zielname);
strcpy (rausname, zielname);
if (extended == '*' && *orgname2)
strncpy (orgname, orgname2, (size_t)(MAXFNAME-1));
fnsplit (rausname, NULL, NULL, zielname, NULL);
rest = (int) (binbytes % 62);
if (!rest)
rest = 62;
parts = teile; /* Set number of parts to decode. */
}
else
*buf = EOS;
/* If more than 1 part, generate filename for messages and handling. */
if (parts != 1)
{
fnsplit (zielname, NULL, NULL, filename, NULL);
strcpy (zielname, filename);
sprintf (dummi, ".p%02x", part);
strcat (filename, dummi);
}
/* Current file does not contain expected part */
if (teil != part)
{
printf ("\007'%s': File does not contain part %03d. Break.\n", filename, part);
kill_dest (rein, raus, orgname);
return (4);
}
/* If correcting, open temp-file, else open output file */
if (correct)
{
strcpy (rausname, tmpfil);
strcpy (orgname , rausname);
raus = fopen (orgname, OPEN_WRITE_TEXT);
}
else
{
/* If first part, check if output file already exists, else prompt for
new name. */
if (part == 1)
{
test_file (rein, orgname, 1, MAXFNAME-1);
raus = fopen (orgname, OPEN_WRITE_BINARY); /* open output file for writing */
}
else /* not first part, open output file for appending */
raus = fopen (orgname, OPEN_APPEND_BINARY);
}
setvbuf (raus, NULL, _IOFBF, buflen); /* As always, bufferize */
/* Correcting, output acording message */
printf ("'%s': ", filename);
if (correct)
{
fprintf (raus, "%s%s", buf, zeile);
printf ("Correcting.\r");
}
else /* Decoding */
{
if (!defekt)
printf ("Decoding"); /* No errors detected, yet */
else
printf ("Testing");
if (parts != 1)
printf (" part %03d of %03d", teil, parts);
printf (". \r");
}
/* This is nessesary on some systems, that bufferize output to the
screen. */
fflush (stdout);
czeile2 = -1;
lokaldefekt = zeilen = corrected = rebuilt = 0;
/* Now decode/correct this part */
do
{
/* Get a line from code file */
p = my_fgets (zeile, 80, rein);
/* If line starts with a space, check if it's the last line */
if (*zeile == ' ')
if (!strncmp (zeile, " stop_7+.", 8))
p = NULL; /* Last line, set end indicator */
if (p)
{
/* Calculate CRC */
csequence = 0;
for (i=0; i<64; i++)
csequence = crctab[csequence>>8] ^ (((csequence&255)<<8) | (byte)p[i]);
csequence &= 0x3fff; /* strip calculated CRC to 14 bits */
/* Get crc from code line */
crc_n_lnum (&crc, &czeile, p);
if (csequence != crc)
{
if (!rebuild (p, 0))
{
ignored++; /* Incorrect CRC. Ignore line. */
continue;
}
rebuilt++;
crc_n_lnum (&crc, &czeile, p);
}
/* Re-arrange data-charaters to 2*8 longs containing 31 bits each.*/
for (i=k=0; i<64; i++)
{
if ((i&3) == 3)
{
danach[k] = 0L;
for (j=i;j>(i-4);j--)
danach[k] = danach[k] * 216L + decode[(byte)p[j]];
k++;
}
}
/* Number of valid binary bytes in this line. If it's the last line
of the last part, set it to the number precalculated earlier */
laenge = 62;
if (czeile == fzeilen && part == parts)
laenge = rest;
}
/* If file ends prematurely, set current line number to number of
lines in this part, so that the missing lines can be protocolled. */
if (!p && fzeilen != czeile)
czeile = fzeilen+1;
/* If current line number is greater than previous one -> ok */
if (czeile > czeile2)
{
/* Difference is greater than 1, then line(s) must be missing. */
if (czeile2 != czeile-1)
{
/* Are we currently correcting? */
if (!correct)
{ /* No, we're not */
/* Open file for error report, if this is the first detected error. */
if (!defekt)
{
sprintf (reportname, "%s.err", zielname);
if ((report = fopen (reportname, OPEN_WRITE_TEXT)) == NULL)
{
printf ("\007Error while writing error report. Break.\n");
fclose (rein);
return (1);
}
strcpy (dummi2, reportname);
strupr (dummi2);
fprintf (report, " go_text. %s%s", dummi2, delimit);
strcpy (dummi2, rausname);
strupr (dummi2);
fprintf (report, "7PLUS error report: %s %03X",
dummi2, blockzeilen);
if (*orgname2)
fprintf (report, " /%s/", orgname2);
fprintf (report, " %ld", binbytes);
fprintf (report, delimit);
}
/* If first error in current part, output number of part */
if (!lokaldefekt)
fprintf (report, "%02X%s", part, delimit);
lokaldefekt = defekt = 1;
}
/* Loop for number of missing or corrupted lines */
for (i = czeile2+1; i < czeile; i++)
{
zeilen++; /* Number of missing or corrupted lines. */
if (!correct)
{
/* Write number of missing line to error report */
printf (miss, i);
fprintf (report, "%03X ", i);
/* Insert line separator, if line full */
if (!(zeilen % 18) && zeilen)
fprintf (report, delimit);
}
else
{
/* Synchronize correction file with current position in code
file, because code file does not necessarily contain as
many errors as covered by correction file */
while ((corrzeile < i && corrpart == part) || corrpart < part)
{
if (!corrpart)
break;
my_fgets (buf, 80, report);
my_fgets (dummi2, 80, report);
corrzeile = get_hex (dummi2+2);
if (dummi2[1] == 'P')
{
corrpart = corrzeile;
if (corrpart)
{
my_fgets (dummi2, 80, report);
corrzeile = get_hex (dummi2+2);
}
else
break;
}
}
/* If error not covered by correction file, tell about it. */
if (corrzeile > i || corrpart != part)
{
printf (miss, i);
fprintf (raus, "Line %03d missing\n", i);
}
/* Error is covered in corretion file. Replace corrupted line
with line from correction file */
if (corrzeile == i && corrpart == part)
{
int x;
my_fgets (buf, 80, report);
csequence = 0;
for (j=0; j<64; j++)
csequence = crctab[csequence>>8] ^ (((csequence&255)<<8) | (byte)buf[j]);
csequence &= 0x3fff;
crc_n_lnum (&crc, &x, buf);
if (csequence == crc && x == i)
{
corrected++; /* Number of corrected lines */
printf ("\n\t\tLine %d replaced.", i);
fprintf (raus, "%s", buf);
}
else
{
if (rebuild (buf, 0))
{
corrected++; /* Number of corrected lines */
printf ("\n\t\tLine %d replaced.", i);
fprintf (raus, "%s", buf);
}
else
fprintf (raus, "%s", zeile);
}
/* Get next info from correction file */
my_fgets (dummi2, 80, report);
corrzeile = get_hex (dummi2+2);
if (dummi2[1] == 'P')
{
corrpart = corrzeile;
if (corrpart)
{
my_fgets (dummi2, 80, report);
corrzeile = get_hex (dummi2+2);
}
}
}
}
}
/* Write previously memorized line. */
if (correct && p)
fprintf (raus, "%s", zeile);
}
else /* Line is OK */
{
/* Only write to output file, if not currently correcting and no
error detected */
if (!correct)
{
if (!lokaldefekt)
{
/* split up longs into 2 * 31 binary bytes and write. */
dn = danach;
for (i=0; i<2; i++, dn+=8)
{
/* Re-arrange to 2*8 longs containing 32 bits. 7th and 15th long
only contain 24 valid bits. */
dn[0] = (dn[0] << 1) | (dn[1] >> 30);
dn[1] = (dn[1] << 2) | (dn[2] >> 29);
dn[2] = (dn[2] << 3) | (dn[3] >> 28);
dn[3] = (dn[3] << 4) | (dn[4] >> 27);
dn[4] = (dn[4] << 5) | (dn[5] >> 26);
dn[5] = (dn[5] << 6) | (dn[6] >> 25);
dn[6] = (dn[6] << 7) | (dn[7] >> 24);
dn[7] = (dn[7] << 8);
for(j=0; j<8; j++)
{
for (k=24;k;k-=8)
{
if (!laenge)
break;
laenge--;
my_putc ((int) (dn[j] >> k), raus);
}
if (j == 7 || !laenge)
break;
laenge--;
my_putc ((int) dn[j], raus);
}
}
}
}
else /* Write previously memorized line, if correcting */
fprintf (raus, "%s", zeile);
}
czeile2 = czeile; /* Memorize current line number */
}
}
while (p); /* Loop until current code file ends */
/* Were there missing/corrupted lines in this part? */
if (zeilen)
{
/* Yes, write FFF to error report to indicate end of this part, tell
about it */
if (!correct)
fprintf (report, "%03X%s", 0xfff, delimit);
printf ("\n\t\tMissing/corrupted lines: %d\n", zeilen);
}
else
if (rebuilt)
printf ("\n");
if (correct)
{
/* Replace end line */
strcpy (dummi2, filename);
strupr (dummi2);
fprintf (raus, " stop_7+. (%s)\n", dummi2);
/* Tell user about success */
if (corrected)
printf ("\t\tCorrected lines: %d\n", corrected);
if (zeilen)
{
cor_ok += (zeilen - corrected);
printf ("\n'%s': Correction", filename);
if (corrected < zeilen)
printf (" not");
printf (" successful.\n\n");
}
if (part == parts)
{
if (!zeilen)
printf ("\n\n");
if (!cor_ok)
printf ("No missing lines.\n");
else
{
printf ("%d lines are still missing!\nRun 7PLUS again to create", cor_ok);
printf (" a new error report.\n");
}
}
}
if (!lokaldefekt && defekt && parts == part && !rebuilt)
puts (spaces);
if ((zeilen || rebuilt) && !correct)
printf ("\n");
fclose (rein);
fclose (raus);
if (correct)
{
/* Erase code file and rename tempfile to code file's name */
if (corrected || ignored)
{
unlink (quellname);
rename (tmpfil, quellname);
}
else /* If no correction made and no errors detected, get rid of tempfile */
unlink (tmpfil);
if (cor_ok && part == parts)
return (16);
}
}
if (!correct)
{
if (defekt) /* Put end line into error report */
{
fprintf (report, "00%s", delimit);
fclose (report);
crc_file (reportname, "7P", "00\n", 0);
report = fopen (reportname, OPEN_APPEND_TEXT);
fprintf (report, " stop_text.%s", delimit);
if (endstr)
fprintf (report, "%s%s", endstr, delimit);
fclose (report);
}
else
{
rein = fopen (orgname, OPEN_READ_TEXT);
fseek (rein, 0L, SEEK_END); /* position read pointer to end of file. */
binb0 = ftell (rein); /* get size. */
fseek (rein, 0L, SEEK_SET); /* reposition to beginning of file. */
fclose (rein);
if (binb0 == binbytes)
{
printf ("\n\nDecoding successful! '%s', %ld bytes.\n\n", orgname, binbytes);
return (0);
}
}
printf ("\n\nDecoding of '%s' not successful.\n\n", orgname);
if (binb0 != binbytes)
printf ("Reason unknown......\n");
else
{
printf ("Send error report '%s' to originator of '%s'\nfor correction.\n",
reportname, orgname);
}
unlink (orgname);
return (11);
}
return (0);
}